package com.inno.lock.processor.distributed;

import cn.hutool.core.lang.Assert;

import com.inno.lock.processor.annotiation.DistributedLock;
import com.inno.lock.config.redis.RedisLockUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * 分布式锁切面
 *
 * @author shenzeyang
 */
@Aspect
@Component
public class DistributedLockAspect {


    private static final Logger log = LoggerFactory.getLogger(DistributedLockAspect.class);

    @Pointcut("@annotation(com.inno.lock.processor.annotiation.DistributedLock)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint point) throws Throwable {
        Method method = ((MethodSignature) point.getSignature()).getMethod();
        DistributedLock lockEnum = method.getAnnotation(DistributedLock.class);

        String key = lockEnum.key();
        Assert.notBlank(key,"[process failed] - DistributedLock.key must have text; it must not be null, empty, or blank");
        long expireTime = lockEnum.expireTime();
        TimeUnit timeUnit = lockEnum.timeUnit();

        try (RedisLockUtil lock = new RedisLockUtil(key,expireTime,timeUnit)) {
            if (lock.tryLock()) {
                log.info("{}:获取锁成功",Thread.currentThread().getName());
                return point.proceed();
            } else {
                log.info("{}:获取锁失败",Thread.currentThread().getName());
                throw new IllegalArgumentException("请稍后重试");
            }
        }
    }
}
